package com.security.control.app.social.openid;

import com.security.control.core.support.SecurityConstants;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.util.Assert;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author imoot@gamil.com
 * @date 2019/1/22 0022 14:55
 * openId身份验证过滤器
 */
public class OpenIdAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    private String openIdParameter = SecurityConstants.DEFAULT_PARAMETER_NAME_OPENID;
    private String providerIdParameter = SecurityConstants.DEFAULT_PARAMETER_NAME_PROVIDERID;
    private boolean postOnly = true;

    public OpenIdAuthenticationFilter() {
        super(new AntPathRequestMatcher(SecurityConstants.DEFAULT_SIGN_IN_PROCESSING_URL_OPENID, "POST"));
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
        //判断如果请求方式不是post，抛出异常
        if (postOnly && !request.getMethod().equals("POST")) {
            throw new AuthenticationServiceException("Authentication requests method not supported : " + request.getMethod());//不支持的身份验证请求方法：请求方式
        }

        //取出服务提供商id和用户在这个服务商下的openId
        String providerId = obtainProviderId(request);
        String openId = obtainOpenId(request);
        //判断服务提供商id和用户的openid如果为空，赋值为空字符串
        if(StringUtils.isBlank(openId)){
            openId = "";
        }
        if(StringUtils.isBlank(providerId)){
            providerId = "";
        }
        //去掉openid和providerId中的空格
        openId = StringUtils.trim(openId);
        providerId = StringUtils.trim(providerId);

        //使用服务提供商id和openid创建OpenIdAuthenticationToken
        OpenIdAuthenticationToken authRequest = new OpenIdAuthenticationToken(openId,providerId);
        //设置子类的详细信息属性
        setDetails(request,authRequest);
        return this.getAuthenticationManager().authenticate(authRequest);
    }

    /**
     * @param request
     * @return String
     * 获取用户的openId
     */
    protected String obtainOpenId(HttpServletRequest request) {
        return request.getParameter(openIdParameter);
    }

    /**
     * @param request
     * @return String
     * 获取服务提供商的id
     */
    protected String obtainProviderId(HttpServletRequest request) {
        return request.getParameter(providerIdParameter);
    }

    /**
     * @param request
     * @param authRequest 这样子类就可以配置身份验证请求的详细信息
     */
    protected void setDetails(HttpServletRequest request, OpenIdAuthenticationToken authRequest) {
        authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
    }

    public String getOpenIdParameter() {
        return openIdParameter;
    }

    public void setOpenIdParameter(String openIdParameter) {
        Assert.hasText(openIdParameter, "Username parameter must not be null or empty");//用户名参数不能为null或者空字符串
        this.openIdParameter = openIdParameter;
    }

    public String getProviderIdParameter() {
        return providerIdParameter;
    }

    public void setProviderIdParameter(String providerIdParameter) {
        this.providerIdParameter = providerIdParameter;
    }

    public void setPostOnly(boolean postOnly) {
        this.postOnly = postOnly;
    }
}
